﻿using System;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;
using Microsoft.Practices.ObjectBuilder2;

using SharedGenomics.Core;

namespace SharedGenomics.Workbench.Aspects
{
    public class CacheCallHandler : ICallHandler
    {
        public CacheCallHandler(ICachingStrategy cachingStrategy)
        {
            this.CachingStrategy = cachingStrategy;
        }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            var args = input.Arguments;
            ExceptionHelper.ThrowIf<InvalidOperationException>(!(args.Count == 1 && args[0].GetType() == typeof(int)), "Can only intercept methods with a single integer argument");

            int id = (int)args[0];

            //return cached item if available
            object cachedItem;
            if (this.CachingStrategy.TryGetFromCache(id, out cachedItem))
            {
                return input.CreateMethodReturn(cachedItem);
            }
            else
            {
                //item not found in cache - call method and cache output if it succeeded
                var returnValue = getNext().Invoke(input, getNext);
                if (returnValue.Exception == null)
                {
                    this.CachingStrategy.AddToCache(id, returnValue.ReturnValue);
                }

                return returnValue;
            }
        }

        public int Order { get; set; }

        private ICachingStrategy CachingStrategy { get; set; }
    }
}
